package cn.ibizlab.util.aspect;

import cn.ibizlab.util.security.AuthenticationUser;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

@Aspect
@Order(50)
@Component
@Slf4j
@ConditionalOnExpression("'${ibiz.tenant.enabled:false}'.equals('true')")
public class TenantAuthenticationAspect {

    /**
     * loadUserByUserName之前填充dc身份查询用户权限数据
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("execution(* cn.ibizlab.core.authentication.service.AuthUserService.loadUserByUsername(..))")
    public Object fillAuthentication(ProceedingJoinPoint point) throws Throwable {
        Object args[] = point.getArgs();
        if (ObjectUtils.isEmpty(args) || args.length == 0) {
            return point.proceed();
        }
        Object arg = args[0];
        if(arg instanceof String){
            String userName = (String) arg;
            String[] usernameArrays = userName.split("[|]");
            //匿名访问
            boolean isAnonymous =  SecurityContextHolder.getContext() == null|| (SecurityContextHolder.getContext() != null && SecurityContextHolder.getContext().getAuthentication() != null
                    && SecurityContextHolder.getContext().getAuthentication() instanceof AnonymousAuthenticationToken);

            if(usernameArrays.length>1 && !ObjectUtils.isEmpty(usernameArrays[1].trim()) && isAnonymous){
                Object result;
                Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
                try {
                    //临时构造dc身份
                    String tenantId = usernameArrays[1].trim();
                    AuthenticationUser authenticationUser = AuthenticationUser.getAuthenticationUser();
                    authenticationUser.setDc(tenantId);
                    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(authenticationUser, null, authenticationUser.getAuthorities());
                    SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                    //带dc身份查询用户权限数据
                    result = point.proceed();
                } finally {
                    //设置为原始用户身份
                    if(isAnonymous)
                        SecurityContextHolder.getContext().setAuthentication(authentication);
                }
                return result;
            }
        }
        return point.proceed();
    }
}
